<?php
require_once 'common.php';
require_once 'OaAppModel.php';
require_once 'OaAppServerConfigLogModel.php';
require_once OA_LIB_PATH . '/inner/service/OAApi.php';
require_once OA_LIB_PATH . '/inner/service/OASApi.php';
require_once OPEN_LIB_PATH . '/open/business-logic/OaSyncInfoLogic.php';

/**
 * 应用服务器模型
 * 
 * 对于所操作环境的设置有三种方式：
 * 1、通过构造函数参数传递默认值；
 * 2、调用接口时显示指定，如果没有指定则使用默认值；
 * 3、通过setCurrentConfigEnv接口修改默认值；
 * 
 * @author wangjiajun
 *
 */
class OaAppServerModel extends OpModel
{
    
    // IDC类型
    const IDC_TYPE_TELECOM = 1;        // 电信
    const IDC_TYPE_CNC = 2;            // 网通
    const IDC_TYPE_BOTH = 3;           // 双线
    const IDC_TYPE_OTHER = 4;          // 其它
    
    // 区有效状态
    const AREA_STATUS_VALID = 1;        // 有效
    const AREA_STATUS_INVALID = 2;      // 无效
    
    // 组有效状态
    const GROUP_STATUS_VALID = 1;        // 有效
    const GROUP_STATUS_INVALID = 2;      // 无效
    
    // 登录服务器有效状态
    const LOGIN_SERVER_STATUS_VALID = 1;        // 有效
    const LOGIN_SERVER_STATUS_INVALID = 2;      // 无效
    
    // 充值服务器有效状态
    const PAY_SERVER_STATUS_VALID = 1;        // 有效
    const PAY_SERVER_STATUS_INVALID = 2;      // 无效
    
    // 充值服务器接口类型
    const PAY_SERVER_TYPE_URL = 1;            // URL
    const PAY_SERVER_TYPE_WEB_SERVICE = 2;    // Web Service
    const PAY_SERVER_TYPE_SOCKET = 3;         // Socket
    
    //充值服务器对应用户账号类型默认值
    const USER_ID_TYPE_DEFAULT = 2;
    
    // 二次确认默认值
    const NEED_CONFIRM = 1;
    
    // 服务器类型
    const APP_SERVER_TYPE_GAME = 1;        // 游戏服务器
    const APP_SERVER_TYPE_LOGIN = 2;       // 登录服务器
    const APP_SERVER_TYPE_PAY = 3;         // 支付服务器
    
	private $_configEnv;
    private $_oaWebDb;
    private $_appAreaTable;
    private $_appGroupTable;
    private $_appServerTable;
    private $_appLoginServerTable;
    private $_appLoginServerValidTable;
    private $_appPayServerTable;
    private $_appPayServerValidTable;
    private $_appSvrCfgLogModel;
	
	public static function getConstantValueByName($name, $default = 0)
    {
        return self::_getConstByName($name, '', $default, 'OaAppServerModel');
    }
    
    public function __construct($env = OaAppModel::APP_CONFIG_ENV_PRODUCTION, $logger = null)
    {
        if (is_null($logger)) {
            $logger = getOaModelLogger();
        }
        parent::__construct($logger);
        
        $this->setCurrentConfigEnv($env);
        
        $dbConfig = Oa_Util_Config::getSingleDbConfig(OA_WEB_DB_CLUSTER_ID);
        $db = OpDbModel::getInstance($dbConfig, $logger);
        $this->_oaWebDb = $db;
        $this->_appAreaTable = new OpTableModel($db, 'app_area', $logger);
        $this->_appGroupTable = new OpTableModel($db, 'app_group', $logger);
        $this->_appServerTable = new OpTableModel($db, 'app_server', $logger);
        $this->_appLoginServerTable = new OpTableModel($db, 'app_login_server', $logger);
        $this->_appLoginServerValidTable = new OpTableModel($db, 'app_login_server_valid', $logger);
        $this->_appPayServerTable = new OpTableModel($db, 'app_pay_server', $logger);
        $this->_appPayServerValidTable = new OpTableModel($db, 'app_pay_server_valid', $logger);
        $this->_appSvrCfgLogModel = new OaAppServerConfigLogModel($logger);
    }
    
    /**
     * 设置当前环境
     * @param int $env
     * @return boolean
     */
    public function setCurrentConfigEnv($env)
    {
        if (!in_array($env, array(OaAppModel::APP_CONFIG_ENV_TEST, 
        	OaAppModel::APP_CONFIG_ENV_PRODUCTION))) {
            $this->_logger->err("invalid env: env-$env");
            return false;
        }
        $this->_configEnv = $env;
        return true;
    }
    
    /**
     * 获取当前环境
     * @return int
     */
    public function getCurrentConfigEnv()
    {
        return $this->_configEnv;
    }
    
    /**
     * 新建分区
     * @param int $appId
     * @param string $name
     * @param int $idcType 为兼容二期数据，IDC类型细分到组级别，以后可能只细分到区级别
     * @param array $row
     * @param boolean $sync
     * @return int|boolean 如果分区代码重复，设置错误号1；分区代码超过999，设置错误号2；名称重复，设置错误号3
     */
    public function addArea($appId, $name, $idcType = 0, $row = array(), $sync = false)
    {
    	$this->_setError();
    	$this->_appAreaTable->filterFields($row);
    	$appModel = new OaAppModel(OaAppModel::APP_CONFIG_ENV_PRODUCTION, $this->_logger);
        $app = $appModel->getApp($appId);
        if (!is_array($app)) {
        	$this->_logger->log("app not exists, app-$appId");
        	return false;
        }
        if (!isset($row['area_code'])) {
            $row['area_code'] = $this->generateAreaCode($appId);
        }
        if (!isset($row['environment'])) {
            $row['environment'] = $this->_configEnv;
        }
        $row = array_merge(array(
            'app_id' => $appId,
            'name' => $name,
            'idc_type' => $idcType,
            'status' => self::AREA_STATUS_VALID,
            'create_time' => date('Y-m-d H:i:s')
        ), $row);
        if ($this->checkAreaCode($appId, $row['area_code'], $row['environment'])) {
            $this->_setError(1, "area code already exists");
            return false;
        }
        if ($row['area_code'] > 999) {
            $this->_setError(2, "area code too large");
            return false;
        }
        if ($this->checkAreaName($appId, $name, $row['environment'])) {
            $this->_setError(3, "area name already exists");
            return false;
        }
        $areaId = $this->_appAreaTable->insert($row);
        if ($areaId === false) {
        	$this->_logger->log("insert failed");
        	return false;
        }
        if ($sync && $row['area_code'] > 0 && !OaSyncInfoLogic::syncAreaInfo($areaId, 'add')) {
            $this->_logger->log("sync area info failed, area-$areaId");
            $this->_appAreaTable->delete(array(
                'id' => $areaId
            ));
            return false;
        }
        $this->_appSvrCfgLogModel->addBackup($appId, OaAppServerConfigLogModel::SERVER_CONFIG_OP_ADD_AREA, 
        	array(), $row, $row['environment']);
        return $areaId;
    }
    
    /**
     * 分配一个区编码
     * @param int $appId
     * @param int $env
     * @return int|boolean
     */
    public function generateAreaCode($appId, $env = null)
    {
        $areas = $this->getAreaList(array(
            'environment' => is_null($env) ? $this->_configEnv : $env,
            'app_id' => $appId
        ), 0, null, 'area_code ASC');
        if ($areas === false) {
            $this->_logger->log("get area list failed");
            return false;
        }
        $i = 0;
        foreach ($areas as $area) {
            if ($area['area_code'] > $i) {
                break;
            }
            $i++;
        }
        return $i;
    }
    
    /**
     * 检查区编码是否已分配过
     * @param int $appId
     * @param int $areaCode
     * @param int $env
     * @return boolean 已存在返回true，否则返回false
     */
    public function checkAreaCode($appId, $areaCode, $env = null)
    {
        $area = $this->_appAreaTable->getRow(array(
            'environment' => is_null($env) ? $this->_configEnv : $env,
            'app_id' => $appId,
            'area_code' => $areaCode
        ));
        return is_array($area) ? true : false;
    }
    
    /**
     * 检查区名是否重复
     * @param int $appId
     * @param string $name
     * @param int $env
     * @return boolean 已存在返回true，否则返回false
     */
    public function checkAreaName($appId, $name, $env = null)
    {
        $area = $this->_appAreaTable->getRow(array(
            'environment' => is_null($env) ? $this->_configEnv : $env,
            'app_id' => $appId,
            'name' => $name
        ));
        return is_array($area) ? true : false;
    }
    
    /**
     * 查询某个区
     * @param int $areaId
     * @return array|null|boolean
     */
    public function getArea($areaId)
    {
        $areaId = (int) $areaId;
        return $this->_appAreaTable->getRow(array(
            'id' => $areaId
        ));
    }
    
    /**
     * 查询多个区
     * @param array $areaIds
     * @return array|boolean
     */
    public function getAreaMulti($areaIds)
    {
        if (empty($areaIds)) {
            return array();
        }
        foreach ($areaIds as &$areaId) {
            $areaId = (int) $areaId;
        }
        unset($areaId);
        $sql = "SELECT * FROM app_area WHERE id IN (" . implode(',', $areaIds) . ")";
        $rows = $this->_appAreaTable->query($sql);
        if ($rows === false) {
        	$this->_logger->log("query failed");
            return false;
        }
        $areas = array();
        foreach ($rows as $row) {
            $areas[$row['id']] = $row;
        }
        return $areas;
    }
    
	/**
     * 根据编码查询某个区
     * @param int $appId
     * @param int $areaCode
     * @param int $env
     * @return array|null|boolean
     */
    public function getAreaByAreaCode($appId, $areaCode, $env = null)
    {
        return $this->_appAreaTable->getRow(array(
            'environment' => is_null($env) ? $this->_configEnv : $env,
            'app_id' => $appId,
            'area_code' => $areaCode
        ));
    }
    
    /**
     * 根据指定条件查询区列表
     * @param array $where
     * @param int $offset
     * @param int $count
     * @param string $sort
     * @param array $otherWhere
     * @return array|boolean
     */
    public function getAreaList($where = null, $offset = 0, $count = null, 
        $sort = null, $otherWhere = null)
    {
        return $this->_appAreaTable->get($where, $offset, $count, $sort, 
            $otherWhere);
    }
    
    /**
     * 查询应用下的区
     * @param int $appId
     * @param int $offset
     * @param int $count
     * @param int $env
     * @return array|boolean
     */
    public function getAppAreas($appId, $offset = 0, $count = null, $env = null)
    {
        return $this->getAreaList(array(
            'environment' => is_null($env) ? $this->_configEnv : (int) $env,
            'app_id' => $appId
        ), $offset, $count, 'id ASC', array(
            array(
                'key' => 'area_code',
                'operation' => '!=',
                'value' => 0
            )
        ));
    }
    
    /**
     * 查询应用下的区数量
     * @param int $appId
     * @param int $env
     * @return int|boolean
     */
    public function getAppAreasCount($appId, $env = null)
    {
    	$appId = (int) $appId;
    	$env = is_null($env) ? $this->_configEnv : (int) $env;
    	$sql = "SELECT COUNT(*) FROM app_area 
    		WHERE app_id=$appId AND environment=$env AND area_code!=0";
    	return $this->_appAreaTable->queryOne($sql);
    }
    
    /**
     * 搜索区
     * @param int $appId
     * @param string $name
     * @param int $env
     * @return array|boolean
     */
    public function searchAreas($appId, $name, $env = null)
    {
    	$appId = (int) $appId;
    	if ($name === '') {
    		return array();
    	}
    	$env = is_null($env) ? $this->_configEnv : (int) $env;
    	$sql = "SELECT * FROM app_area  
    		WHERE app_id=$appId AND environment=$env AND area_code!=0 AND name LIKE " . escapeInputValue("%$name%");
    	return $this->_oaWebDb->query($sql);
    }
    
    /**
     * 修改区
     * @param int $areaId
     * @param array $row
     * @param boolean $sync
     * @return boolean 如果有修改名称且名称重复，设置错误号1
     */
    public function modifyArea($areaId, $row, $sync = false)
    {
    	$this->_setError();
    	$this->_appAreaTable->filterFields($row);
        $area = $this->getArea($areaId);
        if (!is_array($area)) {
            $this->_logger->log("area not exists");
            return false;
        }
        $row = self::filterUnchangedField($row, $area);
        if (empty($row)) {
            return true;
        }
        $oldRow = array();
        foreach ($row as $key => $value) {
        	$oldRow[$key] = $area[$key];
        }
        if (isset($row['name']) && $this->checkAreaName($area['app_id'], $row['name'], $area['environment'])) {
            $this->_setError(1, "area name already exists");
            return false;
        }
        if (!$this->_appAreaTable->update(array(
            'id' => $areaId
        ), $row)) {
        	$this->_logger->log("update failed");
        	return false;
        }
        if ($sync && !OaSyncInfoLogic::syncAreaInfo($areaId, 'update')) {
        	$this->_logger->log("sync area info failed, area-$areaId");
        	$this->modifyArea($areaId, $oldRow);
        	return false;
        }
        $this->_appSvrCfgLogModel->addBackup($area['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_UPDATE_AREA, 
        	$area, $row, $area['environment']);
        return true;
    }
    
    /**
     * 删除区
     * @param int $areaId
     * @param boolean $sync
     * @return boolean
     */
    public function deleteArea($areaId, $sync = false)
    {
    	$this->_setError();
        // 删除区下的组
        if ($this->deleteAreaGroups($areaId, $sync) === false) {
            $this->_logger->log("delete area goups failed");
            return false;
        }
        // 删除生效范围
        if ($this->deleteLoginServerValidAreaByValidAreaId($areaId, $sync) === false) {
            $this->_logger->log("delete login server valid area failed");
            return false;
        }
        if ($this->deletePayServerValidAreaByValidAreaId($areaId, $sync) === false) {
            $this->_logger->log("delete pay server valid area failed");
            return false;
        }
        $area = $this->getArea($areaId);
        if (!is_array($area)) {
            $this->_logger->log("area not exists");
            return false;
        }
        if (!$this->_appAreaTable->delete(array(
            'id' => $areaId
        ))) {
        	$this->_logger->log("delete failed");
        	return false;
        }
        if ($sync && !OaSyncInfoLogic::syncAreaInfo($areaId, 'delete', $area)) {
        	$this->_logger->log("sync area info failed, area-$areaId");
        	$this->addArea($area['app_id'], $area['name'], $area['idc_type'], $area);
        	return false;
        }
        $this->_appSvrCfgLogModel->addBackup($area['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_DELETE_AREA, 
        	$area, array(), $area['environment']);
        return true;
    }
    
    /**
     * 删除应用下的区
     * @param int $appId
     * @param int $env
     * @return boolean
     */
    public function deleteAppAreas($appId, $env = null)
    {
        return $this->_appAreaTable->delete(array(
            'environment' => is_null($env) ? $this->_configEnv : $env,
            'app_id' => $appId
        ));
    }
    
    /**
     * 新建组
     * @param int $areaId
     * @param string $name
     * @param string $idcType
     * @param array $row
     * @param boolean $sync
     * @return int|boolean 如果分组代码重复，设置错误号1；分组代码超过999，设置错误号2；如果名称重复，设置错误号3
     */
    public function addGroup($areaId, $name, $idcType = 0, $row = array(), $sync = false)
    {
    	$this->_setError();
    	$this->_appGroupTable->filterFields($row);
        $area = $this->getArea($areaId);
        if (!is_array($area)) {
            $this->_logger->log("area not exists, area-$areaId");
            return false;
        }
        if (!isset($row['group_code'])) {
            $row['group_code'] = $this->generateGroupCode($areaId);
        }
        $row = array_merge(array(
            'area_id' => $areaId,
            'name' => $name,
            'idc_type' => $idcType,
            'status' => self::GROUP_STATUS_VALID,
            'create_time' => date('Y-m-d H:i:s')
        ), $row);
        if ($this->checkGroupCode($areaId, $row['group_code'])) {
            $this->_setError(1, "group code already exists");
            return false;
        }
        if ($row['group_code'] > 999) {
            $this->_setError(2, "group code too large");
            return false;
        }
        if ($this->checkGroupName($areaId, $name)) {
            $this->_setError(3, "group name already exists");
            return false;
        }
        $groupId = $this->_appGroupTable->insert($row);
        if ($groupId === false) {
        	$this->_logger->log("insert failed");
        	return false;
        }
        if ($sync && $row['group_code'] > 0 && !OaSyncInfoLogic::syncGroupInfo($groupId, 'add')) {
            $this->_logger->log("sync group info failed, group-$groupId");
            $this->_appGroupTable->delete(array(
                'id' => $groupId
            ));
            return false;
        }
        $this->_appSvrCfgLogModel->addBackup($area['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_ADD_GROUP, 
        	array(), $row, $area['environment']);
        return $groupId;
    }
    
    /**
     * 新建组（批量）
     * @param int $areaId
     * @param array $rows
     * @return boolean
     */
    public function addGroupMulti($areaId, $rows)
    {
        $groupIds = array();
        foreach ($rows as $row) {
            if (!isset($row['name'])) {
                $this->_logger->log("no name");
                return false;
            }
            $name = $row['name'];
            $groupId = $this->addGroup($areaId, $name);
            if ($groupId === false) {
                $this->_logger->log("add group failed");
                return false;
            }
            $groupIds[] = $groupId;
        }
        return $groupIds;
    }
    
    /**
     * 分配一个组编码
     * @param int $areaId
     * @return int|boolean
     */
    public function generateGroupCode($areaId)
    {
        $groups = $this->getGroupList(array(
            'area_id' => $areaId
        ), 0, null, 'group_code ASC');
        if ($groups === false) {
            $this->_logger->log("get group list failed");
            return false;
        }
        $i = 1;
        foreach ($groups as $group) {
            if ($group['group_code'] > $i) {
                break;
            }
            $i++;
        }
        return $i;
    }
    
    /**
     * 检查组编码是否已分配
     * @param int $areaId
     * @param int $groupCode
     * @return boolean 已存在返回true，否则返回false
     */
    public function checkGroupCode($areaId, $groupCode)
    {
        $group = $this->_appGroupTable->getRow(array(
            'area_id' => $areaId,
            'group_code' => $groupCode
        ));
        return is_array($group) ? true : false;
    }
    
    /**
     * 检查组名是否重复
     * @param int $areaId
     * @param string $name
     * @return boolean 已存在返回true，否则返回false
     */
    public function checkGroupName($areaId, $name)
    {
        $group = $this->_appGroupTable->getRow(array(
            'area_id' => $areaId,
            'name' => $name
        ));
        return is_array($group) ? true : false;
    }
    
    /**
     * 查询某个组
     * @param int $groupId
     * @return array|null|boolean
     */
    public function getGroup($groupId)
    {
        $groupId = (int) $groupId;
        $sql = "SELECT t.*, t1.area_code, t1.environment, t1.app_id 
        	FROM app_group t  
        	LEFT JOIN app_area t1 ON t.area_id=t1.id 
        	WHERE t.id=$groupId";
        return $this->_oaWebDb->queryRow($sql);
    }
    
	/**
     * 根据编码查询某个组
     * @param int $areaId
     * @param int $groupCode
     * @return array|null|boolean
     */
    public function getGroupByGroupCode($areaId, $groupCode)
    {
        $areaId = (int) $areaId;
        $groupCode = (int) $groupCode;
        $sql = "SELECT t.*, t1.area_code, t1.environment, t1.app_id 
        	FROM app_group t  
        	LEFT JOIN app_area t1 ON t.area_id=t1.id 
        	WHERE t.area_id=$areaId AND t.group_code=$groupCode";
        return $this->_oaWebDb->queryRow($sql);
    }
    
    /**
     * 查询多个组
     * @param array $areaIds
     * @return array|boolean
     */
    public function getGroupMulti($groupIds)
    {
        if (empty($groupIds)) {
            return array();
        }
        foreach ($groupIds as &$groupId) {
            $groupId = (int) $groupId;
        }
        unset($groupId);
        $sql = "SELECT t.*, t1.area_code, t1.environment, t1.app_id 
        	FROM app_group t  
        	LEFT JOIN app_area t1 ON t.area_id=t1.id 
        	WHERE t.id IN (" . implode(',', $groupIds) . ")";
        $rows = $this->_appGroupTable->query($sql);
        if ($rows === false) {
        	$this->_logger->log("query failed");
            return false;
        }
        $groups = array();
        foreach ($rows as $row) {
            $groups[$row['id']] = $row;
        }
        return $groups;
    }
    
    /**
     * 根据指定条件查询组列表
     * @param array $where
     * @param int $offset
     * @param int $count
     * @param string $sort
     * @param array $otherWhere
     * @return array|boolean
     */
    public function getGroupList($where = null, $offset = 0, $count = null, 
        $sort = null, $otherWhere = null)
    {
        return $this->_appGroupTable->get($where, $offset, $count, $sort, 
            $otherWhere);
    }
    
    /**
     * 查询区下的组
     * @param int $areaId
     * @return array|boolean
     */
    public function getAreaGroups($areaId)
    {
    	$areaId = (int) $areaId;
        $sql = "SELECT t.*, t1.area_code, t1.environment, t1.app_id 
        	FROM app_group t  
        	LEFT JOIN app_area t1 ON t.area_id=t1.id 
        	WHERE t.area_id=$areaId AND t.group_code!=0 
        	ORDER BY t.id ASC";
        return $this->_appGroupTable->query($sql);
    }
    
    /**
     * 查询区下的组数量
     * @param int $areaId
     * @return int|boolean
     */
    public function getAreaGroupsCount($areaId)
    {
    	$areaId = (int) $areaId;
        $sql = "SELECT count(*)	FROM app_group 
        	WHERE area_id=$areaId AND group_code!=0";
        return $this->_appServerTable->queryOne($sql);
    }
    
    /**
     * 查询多个区下的组
     * @param array $areaIds
     * @return array|boolean
     */
    public function getAreaGroupsMulti($areaIds)
    {
    	if (empty($areaIds)) {
    		return array();
    	}
    	foreach ($areaIds as &$areaId) {
    		$areaId = (int) $areaId;
    	}
        $sql = "SELECT t.*, t1.area_code, t1.environment, t1.app_id 
        	FROM app_group t  
        	LEFT JOIN app_area t1 ON t.area_id=t1.id 
        	WHERE t.area_id IN (" . implode(',', $areaIds) . ") AND t.group_code!=0 
        	ORDER BY id ASC";
        $rows = $this->_appGroupTable->query($sql);
        if ($rows === false) {
        	$this->_logger->log("query failed");
            return false;
        }
    	$groups = array();
    	foreach ($rows as $row) {
    		$areaId = $row['area_id'];
    		if (isset($groups[$areaId])) {
    			$groups[$areaId][] = $row;
    		} else {
    			$groups[$areaId] = array($row);
    		}
    	}
    	return $groups;
    }
    
    /**
     * 查询区下的组数量（多个）
     * @param array $areaIds
     * @return array|boolean
     */
    public function getAreaGroupsMultiCount($areaIds)
    {
    	if (empty($areaIds)) {
    		return array();
    	}
    	foreach ($areaIds as &$areaId) {
    		$areaId = (int) $areaId;
    	}
        $sql = "SELECT area_id, count(*) AS cnt FROM app_group 
        	WHERE area_id IN (" . implode(',', $areaIds) . ") AND group_code!=0 
        	GROUP BY area_id";
        $rows = $this->_appGroupTable->query($sql);
        if ($rows === false) {
        	return false;
        }
        $counts = array();
        foreach ($rows as $row) {
        	$counts[$row['area_id']] = $row['cnt'];
        }
        return $counts;
    }
    
    /**
     * 查询应用下的组
     * @param int $appId
     * @return array|boolean
     */
    public function getAppGroups($appId, $env = null)
    {
    	$appId = (int) $appId;
    	$env = is_null($env) ? $this->_configEnv : (int) $env;
        $sql = "SELECT t.*, t1.area_code, t1.environment, t1.app_id 
        	FROM app_group t  
        	LEFT JOIN app_area t1 ON t.area_id=t1.id 
        	WHERE t1.app_id=$appId AND t1.environment=$env AND t.group_code!=0 
        	ORDER BY t.id ASC";
        $rows = $this->_oaWebDb->query($sql);
        if ($rows === false) {
        	$this->_logger->log("query failed");
            return false;
        }
    	$groups = array();
    	foreach ($rows as $row) {
    		$areaId = $row['area_id'];
    		if (isset($groups[$areaId])) {
    			$groups[$areaId][] = $row;
    		} else {
    			$groups[$areaId] = array($row);
    		}
    	}
    	return $groups;
    }
    
    /**
     * 搜索组
     * @param int $appId
     * @param string $name
     * @param int $env
     * @return array|boolean
     */
    public function searchGroups($appId, $name, $env = null)
    {
    	$appId = (int) $appId;
    	if ($name === '') {
    		return array();
    	}
    	$env = is_null($env) ? $this->_configEnv : (int) $env;
        $sql = "SELECT t.*, t1.area_code, t1.environment, t1.app_id 
        	FROM app_group t  
        	LEFT JOIN app_area t1 ON t.area_id=t1.id 
    		WHERE t1.app_id=$appId AND t1.environment=$env AND t.group_code!=0
    		AND t.name LIKE " . escapeInputValue("%$name%");
    	return $this->_oaWebDb->query($sql);
    }
    
    /**
     * 修改组
     * @param int $groupId
     * @param array $row
     * @param boolean $sync
     * @return boolean 如果有修改组名且组名重复，设置错误号1
     */
    public function modifyGroup($groupId, $row, $sync = false)
    {
    	$this->_setError();
    	$this->_appGroupTable->filterFields($row);
        $group = $this->getGroup($groupId);
        if (!is_array($group)) {
        	$this->_logger->log("group not exists");
        	return false;
        }
        $row = self::filterUnchangedField($row, $group);
        if (empty($row)) {
            return true;
        }
        $oldRow = array();
        foreach ($row as $key => $value) {
        	$oldRow = $group[$key];
        }
        if (isset($row['name']) && $this->checkGroupName($group['area_id'], $row['name'])) {
            $this->_setError(1, "group name already exists");
            return false;
        }
        if (!$this->_appGroupTable->update(array(
            'id' => $groupId
        ), $row)) {
        	$this->_logger->log("update failed");
        	return false;
        }
        if ($sync && !OaSyncInfoLogic::syncGroupInfo($groupId, 'update')) {
            $this->_logger->log("sync group info failed, group-$groupId");
            $this->modifyGroup($groupId, $oldRow);
            return false;
        }
        $this->_appSvrCfgLogModel->addBackup($group['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_UPDATE_GROUP, 
        	$group, $row, $group['environment']);
        return true;
    }
    
    /**
     * 删除组
     * @param int $groupId
     * @param boolean $sync
     * @return boolean
     */
    public function deleteGroup($groupId, $sync = false)
    {
    	$this->_setError();
        // 删除组下的服务器
        if ($this->deleteGroupServers($groupId, $sync) === false) {
            $this->_logger->log("delete group servers failed");
            return false;
        }
        // 删除生效范围
        if ($this->deleteLoginServerValidAreaByValidGroupId($groupId, $sync) === false) {
            $this->_logger->log("delete login server valid area failed");
            return false;
        }
        if ($this->deletePayServerValidAreaByValidGroupId($groupId, $sync) === false) {
            $this->_logger->log("delete pay server valid area failed");
            return false;
        }
        $group = $this->getGroup($groupId);
        if (!is_array($group)) {
            $this->_logger->log("group not exists, group-$groupId");
            return false;
        }
        if (!$this->_appGroupTable->delete(array(
            'id' => $groupId
        ))) {
        	$this->_logger->log("delete failed");
        	return false;
        }
        if ($sync && !OaSyncInfoLogic::syncGroupInfo($groupId, 'delete', $group)) {
        	$this->_logger->log("sync group info failed, group-$groupId");
        	$this->addGroup($group['area_id'], $group['name'], $group['idc_type'], $group);
        	return false;
        }
        $this->_appSvrCfgLogModel->addBackup($group['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_DELETE_GROUP, 
        	$group, array(), $group['environment']);
        return true;
    }
    
    /**
     * 删除区下的组
     * @param int $areaId
     * @param boolean $sync
     * @return boolean
     */
    public function deleteAreaGroups($areaId, $sync = false)
    {
        $groups = $this->getAreaGroups($areaId);
        if ($groups === false) {
            $this->_logger->log("get area groups failed");
            return false;
        }
        foreach ($groups as $group) {
            if (!$this->deleteGroup($group['id'], $sync)) {
                $this->_logger->log("delete group failed");
                return false;
            }
        }
        return true;
    }
    
    /**
     * 新建服务器
     * @param int $groupId
     * @param string $ip
     * @param string $alias
     * @param array $row
     * @param boolean $sync
     * @return int|boolean ip+alias重复时，设置错误号1
     */
    public function addServer($groupId, $ip, $alias, $row = array(), $sync = false)
    {
    	$this->_setError();
    	$this->_appServerTable->filterFields($row);
        $group = $this->getGroup($groupId);
        if (!is_array($group)) {
            $this->_logger->log("group not exists, group-$groupId");
            return false;
        }
        if (is_array($this->getServerByIpAlias($ip, $alias, $group['environment']))) {
            $this->_setError(1, "ip alias duplicated");
            return false;
        }
        $message = '';
        $ipInfo = OASApi::ip($message, array(
        	'clientIp' => $ip, 
        	'alias' => $alias
        ), 'select', $group['environment']);
        if ($ipInfo && $ipInfo['appId'] != $group['app_id']) {
            $this->_setError(1, "ip alias duplicated");
            return false;
        }
        $row = array_merge(array(
            'group_id' => $groupId,
            'ip' => $ip,
            'alias' => $alias,
            'create_time' => date('Y-m-d H:i:s')
        ), $row);
        $serverId = $this->_appServerTable->insert($row);
        if (!$serverId) {
        	$this->_logger->log("insert failed");
        	return false;
        }
        if ($sync && !OaSyncInfoLogic::syncServerInfo($serverId, 'add')) {
            $this->_logger->log("sync server info failed, server-$serverId");
            $this->_appServerTable->delete(array(
                'id' => $serverId
            ));
            return false;
        }
        $this->_appSvrCfgLogModel->addBackup($group['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_ADD_SERVER, 
        	array(), $row, $group['environment']);
        return $serverId;
    }
    
    /**
     * 新建服务器（批量）
     * @param int $groupId
     * @param array $rows
     * @return array|boolean 如果ip+alias重复，设置错误号1
     */
    public function addServerMulti($groupId, $rows)
    {
        $serverIds = array();
        foreach ($rows as $row) {
            if (!isset($row['ip'])) {
                $this->_logger->log("no ip");
                return false;
            }
            $ip = $row['ip'];
            if (!isset($row['alias'])) {
                $this->_logger->log("no alias");
                return false;
            }
            $alias = $row['alias'];
            $serverId = $this->addServer($groupId, $ip, $alias, $rows);
            if ($serverId === false) {
                foreach ($serverIds as $serverId) {
                    $this->deleteServer($serverId);
                }
                if ($this->getErrorNo() == 1) {
                    $this->_setError(1, "ip alias duplicated");
                    return false;
                }
                $this->_logger->log("add server failed");
                return false;
            }
            $serverIds[] = $serverId;
        }
        return $serverIds;
    }
    
    /**
     * 查询服务器
     * @param int $serverId
     * @return array|null|boolean
     */
    public function getServer($serverId)
    {
        $serverId = (int) $serverId;
        $sql = "SELECT t.*, t1.group_code, t1.idc_type, t2.id AS area_id, t2.area_code, 
        	t2.environment, t2.app_id 
        	FROM app_server t
        	LEFT JOIN app_group t1  ON (t.group_id=t1.id)
        	LEFT JOIN app_area t2 ON (t1.area_id=t2.id)
        	WHERE t.id=$serverId";
        return $this->_oaWebDb->queryRow($sql);
    }
    
    /**
     * 查询服务器（批量）
     * @param array $areaIds
     * @return array|boolean
     */
    public function getServerMulti($serverIds)
    {
        if (empty($serverIds)) {
            return array();
        }
        foreach ($serverIds as &$serverId) {
            $serverId = (int) $serverId;
        }
        unset($serverId);
        $sql = "SELECT t.*, t1.group_code, t1.idc_type, t2.id AS area_id, t2.area_code, 
        	t2.environment, t2.app_id 
        	FROM app_server t
        	LEFT JOIN app_group t1  ON (t.group_id=t1.id)
        	LEFT JOIN app_area t2 ON (t1.area_id=t2.id)
        	WHERE t.id IN (" . implode(',', $serverIds) . ")";
        $rows = $this->_appServerTable->query($sql);
        if ($rows === false) {
        	$this->_logger->log("query failed");
            return false;
        }
        $servers = array();
        foreach ($rows as $row) {
            $servers[$row['id']] = $row;
        }
        return $servers;
    }
    
    /**
     * 根据ip和别名查询服务器
     * @param string $ip
     * @param string $alias
     * @param int $env
     * @return array|null|boolean 如果没有找到，返回null
     */
    public function getServerByIpAlias($ip, $alias, $env = null)
    {
    	if (is_null($env)) {
    		$env = $this->_configEnv;
    	}
        $sql = "SELECT t.*, t1.group_code, t1.idc_type, t2.id AS area_id, t2.area_code, 
        	t2.environment, t2.app_id 
        	FROM app_server t
        	LEFT JOIN app_group t1  ON (t.group_id=t1.id)
        	LEFT JOIN app_area t2 ON (t1.area_id=t2.id)
        	WHERE t.ip=" . escapeInputValue($ip) . 
        	" AND t.alias=" . escapeInputValue($alias) . 
        	" AND t2.environment=" . escapeInputValue($env);
        return $this->_oaWebDb->queryRow($sql);
    }
    
    /**
     * 根据IPID查询服务器
     * @param int $ipId
     * @param int $env
     * @return array|null|boolean 如果没有找到，返回null
     */
    public function getServerByIpId($ipId, $env = null)
    {
    	if (is_null($env)) {
    		$env = $this->_configEnv;
    	}
        $sql = "SELECT t.*, t1.group_code, t1.idc_type, t2.id AS area_id, t2.area_code, 
        	t2.environment, t2.app_id 
        	FROM app_server t
        	LEFT JOIN app_group t1  ON (t.group_id=t1.id)
        	LEFT JOIN app_area t2 ON (t1.area_id=t2.id)
        	WHERE t.ip_id=" . escapeInputValue($ipId) . 
        	" AND t2.environment=" . escapeInputValue($env);
        return $this->_oaWebDb->queryRow($sql);
    }
    
    /**
     * 根据指定条件查询服务器列表
     * @param array $where
     * @param int $offset
     * @param int $count
     * @param string $sort
     * @param array $otherWhere
     * @return array|boolean
     */
    public function getServerList($where = null, $offset = 0, $count = null, 
        $sort = null, $otherWhere = null)
    {
        return $this->_appServerTable->get($where, $offset, $count, $sort, 
            $otherWhere);
    }
    
    /**
     * 查询组下的服务器
     * @param int $groupId
     * @param int $offset
     * @param int $count
     * @return array|boolean
     */
    public function getGroupServers($groupId, $offset = 0, $count = null)
    {
    	$groupId = (int) $groupId;
        $sql = "SELECT t.*, t1.group_code, t1.idc_type, t2.id AS area_id, t2.area_code, 
        	t2.environment, t2.app_id 
        	FROM app_server t
        	LEFT JOIN app_group t1  ON (t.group_id=t1.id)
        	LEFT JOIN app_area t2 ON (t1.area_id=t2.id)
        	WHERE t.group_id=$groupId 
        	ORDER BY t.id ASC";
        return $this->_appServerTable->query($sql);
    }
    
    /**
     * 查询组下的服务器数量
     * @param int $groupId
     * @return int|boolean
     */
    public function getGroupServersCount($groupId)
    {
    	$groupId = (int) $groupId;
        $sql = "SELECT count(*)	FROM app_server WHERE group_id=$groupId";
        return $this->_appServerTable->queryOne($sql);
    }
    
    /**
     * 查询组下的服务器（多个）
     * @param array $groupIds
     * @return array|boolean
     */
    public function getGroupServersMulti($groupIds)
    {
    	if (empty($groupIds)) {
    		return array();
    	}
    	foreach ($groupIds as &$groupId) {
    		$groupId = (int) $groupId;
    	}
        $sql = "SELECT t.*, t1.group_code, t1.idc_type, t2.id AS area_id, t2.area_code, 
        	t2.environment, t2.app_id 
        	FROM app_server t
        	LEFT JOIN app_group t1  ON (t.group_id=t1.id)
        	LEFT JOIN app_area t2 ON (t1.area_id=t2.id)
        	WHERE t.group_id IN (" . implode(',', $groupIds) . ") 
        	ORDER BY t.id ASC";
        $rows = $this->_appServerTable->query($sql);
        if ($rows === false) {
        	$this->_logger->log("query failed");
            return false;
        }
    	$servers = array();
    	foreach ($rows as $row) {
    		$groupId = $row['group_id'];
    		if (isset($servers[$groupId])) {
    			$servers[$groupId][] = $row;
    		} else {
    			$servers[$groupId] = array($row);
    		}
    	}
    	return $servers;
    }
    
    /**
     * 查询组下的服务器数量（多个）
     * @param array $groupIds
     * @return array|boolean
     */
    public function getGroupServersMultiCount($groupIds)
    {
    	if (empty($groupIds)) {
    		return array();
    	}
    	foreach ($groupIds as &$groupId) {
    		$groupId = (int) $groupId;
    	}
        $sql = "SELECT group_id, count(*) AS cnt FROM app_server 
        	WHERE group_id IN (" . implode(',', $groupIds) . ") 
        	GROUP BY group_id";
        $rows = $this->_appServerTable->query($sql);
        if ($rows === false) {
        	return false;
        }
        $counts = array();
        foreach ($rows as $row) {
        	$counts[$row['group_id']] = $row['cnt'];
        }
        return $counts;
    }
    
    /**
     * 查询应用下的服务器
     * @param int $appId
     * @return array|boolean
     */
    public function getAppServers($appId, $env = null)
    {
    	$appId = (int) $appId;
    	$env = is_null($env) ? $this->_configEnv : (int) $env;
        $sql = "SELECT t.*, t1.group_code, t1.idc_type, t2.id AS area_id, t2.area_code, 
        	t2.environment, t2.app_id 
        	FROM app_server t
        	LEFT JOIN app_group t1  ON (t.group_id=t1.id)
        	LEFT JOIN app_area t2 ON (t1.area_id=t2.id)
        	WHERE t2.app_id=$appId AND t2.environment=$env 
        	ORDER BY t.id ASC";
        $rows = $this->_oaWebDb->query($sql);
        if ($rows === false) {
        	$this->_logger->log("query failed");
            return false;
        }
    	$servers = array();
    	foreach ($rows as $row) {
    		$groupId = $row['group_id'];
    		if (isset($servers[$groupId])) {
    			$servers[$groupId][] = $row;
    		} else {
    			$servers[$groupId] = array($row);
    		}
    	}
    	return $servers;
    }
    
    /**
     * 搜索服务器
     * @param int $appId
     * @param string $ip null表示该参数不起作用 
     * @param string $alias null表示该参数不起作用 
     * @param int $env
     * @return array|boolean
     */
    public function searchServers($appId, $ip = null, $alias = null, $env = null)
    {
    	$appId = (int) $appId;
    	if ($ip === '' || $alias === '') {
    		return array();
    	}
    	$env = is_null($env) ? $this->_configEnv : (int) $env;
        $sql = "SELECT t.*, t1.group_code, t1.idc_type, t2.id AS area_id, t2.area_code, 
        	t2.environment, t2.app_id 
        	FROM app_server t
        	LEFT JOIN app_group t1  ON (t.group_id=t1.id)
        	LEFT JOIN app_area t2 ON (t1.area_id=t2.id)
    		WHERE t2.app_id=$appId AND t2.environment=$env";
    	if (!is_null($ip)) {
    	    $sql .= " AND t.ip LIKE " . escapeInputValue("%$ip%");
    	}
    	if (!is_null($alias)) {
    	    $sql .= " AND t.alias LIKE " . escapeInputValue("%$alias%");
    	}
    	return $this->_oaWebDb->query($sql);
    }
    
    /**
     * 修改服务器
     * @param int $serverId
     * @param array $row
     * @param boolean $sync
     * @return boolean 如果跟已有重复，设置错误号1
     */
    public function modifyServer($serverId, $row, $sync = false)
    {
    	$this->_setError();
    	$this->_appServerTable->filterFields($row);
        $server = $this->getServer($serverId);
        if (!is_array($server)) {
            $this->_logger->log("server not exists");
            return false;
        }
        $row = self::filterUnchangedField($row, $server);
        if (empty($row)) {
            return true;
        }
        $oldRow = array();
        foreach ($row as $key => $value) {
        	$oldRow[$key] = $server[$key];
        }
        if (isset($row['ip']) || isset($row['alias'])) {
            $ip = isset($row['ip']) ? $row['ip'] : $server['ip'];
            $alias = isset($row['alias']) ? $row['alias'] : $server['alias'];
            if (is_array($this->getServerByIpAlias($ip, $alias, $server['environment']))) {
                $this->_setError(1, "ip alias duplicated");
                return false;
            }
            $message = '';
            $ipInfo = OASApi::ip($message, array(
            	'clientIp' => $ip, 
            	'alias' => $alias
            ), 'select', $server['environment']);
            if ($ipInfo && $ipInfo['appId'] != $server['app_id']) {
                $this->_setError(1, "ip alias duplicated");
                return false;
            }
        }
        if (!$this->_appServerTable->update(array(
            'id' => $serverId
        ), $row)) {
        	$this->_logger->log("update failed");
        	return false;
        }
        if ($sync) {
            $newServer = array_merge($server, $row);
            $newServer['old_ip'] = $server['ip'];
            $newServer['old_alias'] = $server['alias'];
            if (!OaSyncInfoLogic::syncServerInfo($serverId, 'update', $newServer)) {
                $this->_logger->log("sync pay server info failed, server-$serverId");
                $this->modifyServer($serverId, $oldRow);
                return false;
            }
        }
        $this->_appSvrCfgLogModel->addBackup($server['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_UPDATE_SERVER, 
        	$server, $row, $server['environment']);
        return true;
    }
    
    /**
     * 删除服务器
     * @param int $serverId
     * $param boolean $sync
     * @return boolean
     */
    public function deleteServer($serverId, $sync = false)
    {
    	$this->_setError();
        // 删除生效范围
        if ($this->deleteLoginServerValidAreaByValidServerId($serverId, $sync) === false) {
            $this->_logger->log("delete login server valid area failed");
            return false;
        }
        if ($this->deletePayServerValidAreaByValidServerId($serverId, $sync) === false) {
            $this->_logger->log("delete pay server valid area failed");
            return false;
        }
        $server = $this->getServer($serverId);
        if (!is_array($server)) {
            $this->_logger->log("server not exists, server-$serverId");
            return false;
        }
        if (!$this->_appServerTable->delete(array(
            'id' => $serverId
        ))) {
        	$this->_logger->log("delete failed");
        	return false;
        }
        if ($sync && !OaSyncInfoLogic::syncServerInfo($serverId, 'delete', $server)) {
            $this->_logger->log("sync server info failed, server-$serverId");
            $this->addServer($server['group_id'], $server['ip'], $server['alias'], $server);
            return false;
        }
        $this->_appSvrCfgLogModel->addBackup($server['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_DELETE_SERVER, 
        	$server, array(), $server['environment']);
        return true;
    }
    
    /**
     * 删除组下的服务器
     * @param int $groupId
     * @param boolean $sync
     * @return boolean
     */
    public function deleteGroupServers($groupId, $sync = false)
    {
        $servers = $this->getGroupServers($groupId);
        if ($servers === false) {
            $this->_logger->log("get group servers failed");
            return false;
        }
        foreach ($servers as $server) {
            if (!$this->deleteServer($server['id'], $sync)) {
                $this->_logger->log("delete server failed");
                return false;
            }
        }
        return true;
    }
    
    /**
     * 新建登录服务器
     * @param int $appId
     * @param string $ip
     * @param string $alias
     * @param int $idcType
     * @param array $row
     * @param boolean $sync
     * @return int|boolean ip+alias重复时，设置错误号1
     */
    public function addLoginServer($appId, $ip, $alias, $idcType, $row = array(), $sync = false)
    {
    	$this->_setError();
    	$this->_appLoginServerTable->filterFields($row);
        $row = array_merge(array(
            'environment' => $this->_configEnv,
            'app_id' => $appId,
            'ip' => $ip,
            'alias' => $alias,
            'idc_type' => $idcType,
            'create_time' => date('Y-m-d H:i:s')
        ), $row);
        if (is_array($this->getLoginServerByIpAlias($ip, $alias, $row['environment']))) {
            $this->_setError(1, "ip alias duplicated");
            return false;
        }
        /*判断rsa加密模式下，是否与计费服务器IP冲突*/
        $appInfo = $this->appModel->getApp($appId, array('encrypt_type', 'pay_type'));
        if ($appInfo['pay_type']!=OaAppModel::APP_PAY_TYPE_FREE && $appInfo['encrypt_type']==OaAppModel::APP_ENCRYPT_TYPE_RSA 
        && is_array($this->getPayServerByIpAlias($ip, $alias, $row['environment']))) {
        	$this->_setError(1, "ip alias duplicated");
            return false;
        }
        $message = '';
        $ipInfo = OASApi::ip($message, array(
        	'clientIp' => $ip, 
        	'alias' => $alias
        ), 'select', $row['environment']);
        if ($ipInfo && $ipInfo['appId'] != $row['app_id']) {
            $this->_setError(1, "ip alias duplicated");
            return false;
        }
        $loginServerId = $this->_appLoginServerTable->insert($row);
        if ($loginServerId === false) {
        	$this->_logger->log("insert failed");
        	return false;
        }
        if ($sync && !OaSyncInfoLogic::syncLoginServerInfo($loginServerId, 'add')) {
        	$this->_logger->log("sync login server info failed, login_server-$loginServerId");
        	$this->_appLoginServerTable->delete(array(
        	    'id' => $loginServerId
        	));
        	return false;
        }
        $this->_appSvrCfgLogModel->addBackup($appId, OaAppServerConfigLogModel::SERVER_CONFIG_OP_ADD_LOGIN_SERVER, 
        	array(), $row, $row['environment']);
        return $loginServerId;
    }
    
    /**
     * 查询登录服务器
     * @param int $serverId
     * @return array|null|boolean
     */
    public function getLoginServer($loginServerId)
    {
        return $this->_appLoginServerTable->getRow(array(
            'id' => $loginServerId
        ));
    }
    
    /**
     * 查询登录服务器（批量）
     * @param array $loginServerIds
     * @return array|boolean
     */
    public function getLoginServerMulti($loginServerIds)
    {
        if (empty($loginServerIds)) {
            return array();
        }
        foreach ($loginServerIds as &$loginServerId) {
            $loginServerId = (int) $loginServerId;
        }
        unset($loginServerId);
        $sql = "SELECT * FROM app_login_server WHERE id IN (" . implode(',', $loginServerIds) . ")";
        $rows = $this->_appLoginServerTable->query($sql);
        if ($rows === false) {
        	$this->_logger->log("query failed");
            return false;
        }
        $loginServers = array();
        foreach ($rows as $row) {
            $loginServers[$row['id']] = $row;
        }
        return $loginServers;
    }
    
    /**
     * 根据ip和别名查询登录服务器
     * @param string $ip
     * @param string $alias
     * @param int $env
     * @return array|null|boolean 如果没有找到，返回null
     */
    public function getLoginServerByIpAlias($ip, $alias, $env = null)
    {
        return $this->_appLoginServerTable->getRow(array(
            'environment' => is_null($env) ? $this->_configEnv : $env,
            'ip' => $ip,
            'alias' => $alias
        ));
    }
    
    /**
     * 根据IPID查询登录服务器
     * @param int $ipId
     * @param int $env
     * @return array|null|boolean 如果没有找到，返回null
     */
    public function getLoginServerByIpId($ipId, $env = null)
    {
        return $this->_appLoginServerTable->getRow(array(
            'environment' => is_null($env) ? $this->_configEnv : $env,
            'ip_id' => $ipId
        ));
    }
    
    /**
     * 查询应用登录服务器列表
     * @param int $appId
     * @param int $env
     * @return array|boolean
     */
    public function getAppLoginServers($appId, $env = null)
    {
        return $this->_appLoginServerTable->get(array(
            'environment' => is_null($env) ? $this->_configEnv : $env,
            'app_id' => $appId
        ), 0, null, 'id ASC');
    }
    
    /**
     * 搜索登录服务器
     * @param int $appId
     * @param string $ip null表示该参数不起作用
     * @param string $alias null表示该参数不起作用
     * @param int $env
     * @return array|boolean
     */
    public function searchLoginServers($appId, $ip = null, $alias = null, $env = null)
    {
    	$appId = (int) $appId;
    	if ($ip === '' || $alias === '') {
    		return array();
    	}
    	$env = is_null($env) ? $this->_configEnv : (int) $env;
    	$sql = "SELECT t.* FROM app_login_server AS t 
    		WHERE app_id=$appId AND environment=$env";
    	if (!is_null($ip)) {
    	    $sql .= " AND t.ip LIKE " . escapeInputValue("%$ip%");
    	}
    	if (!is_null($alias)) {
    	    $sql .= " AND t.alias LIKE " . escapeInputValue("%$alias%");
    	}
    	return $this->_oaWebDb->query($sql);
    }
    
    /**
     * 修改登录服务器
     * @param int $loginServerId
     * @param array $row
     * @param boolean $sync
     * @return boolean 如果ip+alias重复，设置错误号1
     */
    public function modifyLoginServer($loginServerId, $row, $sync = false)
    {
    	$this->_setError();
    	$this->_appLoginServerTable->filterFields($row);
        $loginServer = $this->getLoginServer($loginServerId);
        if (!is_array($loginServer)) {
            $this->_logger->log("server not exists");
            return false;
        }
        $row = self::filterUnchangedField($row, $loginServer);
        if (empty($row)) {
            return true;
        }
        $oldRow = array();
        foreach ($row as $key => $value) {
        	$oldRow[$key] = $loginServer[$key];
        }
        if (isset($row['ip']) || isset($row['alias'])) {
            $ip = isset($row['ip']) ? $row['ip'] : $loginServer['ip'];
            $alias = isset($row['alias']) ? $row['alias'] : $loginServer['alias'];
            if (is_array($this->getLoginServerByIpAlias($ip, $alias, $loginServer['environment']))) {
                $this->_setError(1, "ip alias duplicated");
                return false;
            }
            /*判断rsa加密模式下，是否与计费服务器IP冲突*/
            $appInfo = $this->appModel->getApp($loginServer['app_id'], array('encrypt_type', 'pay_type'));
            if ($appInfo['pay_type']!=OaAppModel::APP_PAY_TYPE_FREE && $appInfo['encrypt_type']==OaAppModel::APP_ENCRYPT_TYPE_RSA 
            && is_array($this->getPayServerByIpAlias($ip, $alias, $loginServer['environment']))) {
            	$this->_setError(1, "ip alias duplicated");
                return false;
            }
            $message = '';
            $ipInfo = OASApi::ip($message, array(
            	'clientIp' => $ip, 
            	'alias' => $alias
            ), 'select', $loginServer['environment']);
            if ($ipInfo && $ipInfo['appId'] != $loginServer['app_id']) {
                $this->_setError(1, "ip alias duplicated");
                return false;
            }
        }
        if (!$this->_appLoginServerTable->update(array(
            'id' => $loginServerId
        ), $row)) {
        	$this->_logger->log("update failed");
        	return false;
        }
        if ($sync) {
	        $newLoginServer = array_merge($loginServer, $row);
	        $newLoginServer['old_ip'] = $loginServer['ip'];
	        $newLoginServer['old_alias'] = $loginServer['alias'];
	        if (!OaSyncInfoLogic::syncLoginServerInfo($loginServerId, 'update', $newLoginServer)) {
	        	$this->_logger->log("sync login server info failed, login_server-$loginServerId");
	        	$this->modifyLoginServer($loginServerId, $oldRow);
	        	return false;
	        }
	        $loginServerValidTos = $this->getLoginServerValidTo($loginServerId);
	        foreach ($loginServerValidTos as $validTo) {
		        if (!OaSyncInfoLogic::syncLoginServerValidToInfo($validTo['id'], 'update', $validTo)) {
		            $this->_logger->log("sync login server valid info failed, op-update, " . 
		            	"valid_row-{$validTo['id']}");
		        }
	        }
        }
        $this->_appSvrCfgLogModel->addBackup($loginServer['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_UPDATE_LOGIN_SERVER, 
        	$loginServer, $row, $loginServer['environment']);
        return true;
    }
    
    /**
     * 删除登录服务器
     * @param int $loginServerId
     * @param boolean $sync
     * @return boolean
     */
    public function deleteLoginServer($loginServerId, $sync = false)
    {
    	$this->_setError();
        $loginServer = $this->getLoginServer($loginServerId);
        if (!is_array($loginServer)) {
        	$this->_logger->log("login server not exists, login_server-$loginServerId");
        	return false;
        }
        if ($this->deleteLoginServerValidAreaByLoginServerId($loginServerId, $sync) === false) {
            $this->_logger->log("delete valid areas of login server failed");
            return false;
        }
        if (!$this->_appLoginServerTable->delete(array(
            'id' => $loginServerId
        ))) {
        	$this->_logger->log("delete failed");
        	return false;
        }
        if ($sync && !OaSyncInfoLogic::syncLoginServerInfo($loginServerId, 'delete', $loginServer)) {
        	$this->_logger->log("sync login server info failed, login_server-$loginServerId");
        	$this->addLoginServer($loginServer['app_id'], $loginServer['ip'], $loginServer['alias'], 
        		$loginServer['idc_type'], $loginServer);
        	return false;
        }
        $this->_appSvrCfgLogModel->addBackup($loginServer['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_DELETE_LOGIN_SERVER, 
        	$loginServer, array(), $loginServer['environment']);
        return true;
    }
    
    /**
     * 删除应用登录服务器
     * @param int $appId
     * @param int $env
     * @return boolean
     */
    public function deleteAppLoginServers($appId, $env = null)
    {
        return $this->_appLoginServerTable->delete(array(
            'environment' => is_null($env) ? $this->_configEnv : $env,
            'app_id' => $appId
        ));
    }
    
    /**
     * 增加登录服务器生效范围，一个生效范围可以配置多台登录服务器
     * @param int $loginServerId
     * @param int $validToArea
     * @param int $validToGroup
     * @param int $validToServer
     * @param array $row
     * @param boolean $sync
     * @return int|boolean 如果生效范围冲突，设置错误号1
     */
    public function addLoginServerValidTo($loginServerId, $validToArea = -1, $validToGroup = -1, 
        $validToServer = -1, $row = array(), $sync = false)
    {
    	$this->_setError();
    	$this->_appLoginServerValidTable->filterFields($row);
        $loginServer = $this->getLoginServer($loginServerId);
        if (!is_array($loginServer)) {
        	$this->_logger->log("login server not exists, login_server-$loginServerId");
        	return false;
        }
        if (!$this->checkLoginServerValidTo($loginServerId, $validToArea, $validToGroup, $validToServer)) {
            $this->_setError(1, "already exists");
            return false;
        }
        $row = array_merge(array(
            'valid_to_area' => $validToArea,
            'valid_to_group' => $validToGroup,
            'valid_to_server' => $validToServer,
            'login_server_id' => $loginServerId,
            'status' => self::LOGIN_SERVER_STATUS_VALID
        ), $row);
        $id = $this->_appLoginServerValidTable->insert($row);
        if ($id === false) {
            $this->_logger->log("add login server valid row failed");
            return false;
        }
        if ($sync && !OaSyncInfoLogic::syncLoginServerValidToInfo($id, 'add')) {
            $this->_logger->log("sync login server valid row failed, valid_row-$id");
            $this->_appLoginServerValidTable->delete(array(
                'id' => $id
            ));
            return false;
        }
        $this->_appSvrCfgLogModel->addBackup($loginServer['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_ADD_LOGIN_SERVER_VALID_TO, 
        	array(), $row, $loginServer['environment']);
        return $id;
    }
    
    /**
     * 检查登录服务器生效范围
     * @param int $loginServerId
     * @param int $validToArea
     * @param int $validToGroup
     * @param int $validToServer
     * @return boolean
     */
    public function checkLoginServerValidTo($loginServerId, $validToArea, $validToGroup, $validToServer)
    {
        return is_null($this->_appLoginServerValidTable->getRow(array(
            'valid_to_area' => $validToArea,
            'valid_to_group' => $validToGroup,
            'valid_to_server' => $validToServer,
            'login_server_id' => $loginServerId
        )));
    }
    
    /**
     * 查询登录服务器生效范围（根据自增长ID）
     * @param int $id
     * @return array|null|boolean
     */
    public function getLoginServerValidToById($id)
    {
        $id = (int) $id;
        $sql = "SELECT t.*, t1.area_code, t1.name AS area_name, t2.group_code, t2.name AS group_name, 
        	t3.ip_id AS server_ip_id, t3.ip AS server_ip, t3.alias AS server_alias, 
        	t4.ip_id, t4.ip, t4.alias, t4.environment, t4.idc_type, t4.app_id 
        	FROM app_login_server_valid AS t 
        	LEFT JOIN app_area AS t1 ON t.valid_to_area=t1.id 
        	LEFT JOIN app_group AS t2 ON t.valid_to_group=t2.id 
        	LEFT JOIN app_server AS t3 ON t.valid_to_server=t3.id 
        	LEFT JOIN app_login_server AS t4 ON t.login_server_id=t4.id 
    		WHERE t.id=$id";
        return $this->_oaWebDb->queryRow($sql);
    }
    
    /**
     * 查询登录服务器生效范围（根据区、组、服务器）
     * @param int $validToArea
     * @param int $validToGroup
     * @param int $validToServer
     * @param int $appId
     * @param int $env
     * @return array|boolean
     */
    public function getLoginServerValidToByAGS($validToArea, $validToGroup = null, 
    	$validToServer = null, $appId = null, $env = null)
    {
        $validToArea = (int) $validToArea;
        $sql = "SELECT t.*, t1.area_code, t1.name AS area_name, t2.group_code, t2.name AS group_name, 
        	t3.ip_id AS server_ip_id, t3.ip AS server_ip, t3.alias AS server_alias, 
        	t4.ip_id, t4.ip, t4.alias, t4.environment, t4.idc_type, t4.app_id 
        	FROM app_login_server_valid AS t 
        	LEFT JOIN app_area AS t1 ON t.valid_to_area=t1.id 
        	LEFT JOIN app_group AS t2 ON t.valid_to_group=t2.id 
        	LEFT JOIN app_server AS t3 ON t.valid_to_server=t3.id 
        	LEFT JOIN app_login_server AS t4 ON t.login_server_id=t4.id 
    		WHERE t.valid_to_area=$validToArea";
    	if (!is_null($validToGroup)) {
        	$validToGroup = (int) $validToGroup;
            $sql .= " AND t.valid_to_group=$validToGroup";
        }
    	if (!is_null($validToServer)) {
        	$validToServer = (int) $validToServer;
            $sql .= " AND t.valid_to_server=$validToServer";
        }
    	if (!is_null($appId)) {
            $appId = (int) $appId;
            $sql .= " AND t4.app_id=$appId";
        }
        if (!is_null($env)) {
            $env = (int) $env;
            $sql .= " AND t4.environment=$env";
        }
        $sql .= " ORDER BY t.id ASC";
        return $this->_oaWebDb->query($sql);
    }
    
    /**
     * 查询登录服务器生效范围（根据登录服务器）
     * @param int $loginServerId
     * @return array|boolean
     */
    public function getLoginServerValidTo($loginServerId)
    {
        $loginServerId = (int) $loginServerId;
        $sql = "SELECT t.*, t1.area_code, t1.name AS area_name, t2.group_code, t2.name AS group_name, 
        	t3.ip_id AS server_ip_id, t3.ip AS server_ip, t3.alias AS server_alias, 
        	t4.ip_id, t4.ip, t4.alias, t4.environment, t4.idc_type, t4.app_id 
        	FROM app_login_server_valid AS t 
        	LEFT JOIN app_area AS t1 ON t.valid_to_area=t1.id 
        	LEFT JOIN app_group AS t2 ON t.valid_to_group=t2.id 
        	LEFT JOIN app_server AS t3 ON t.valid_to_server=t3.id 
        	LEFT JOIN app_login_server AS t4 ON t.login_server_id=t4.id 
    		WHERE t.login_server_id=$loginServerId 
    		ORDER BY t.id ASC";
        return $this->_oaWebDb->query($sql);
    }
    
    /**
     * 查询应用登录服务器生效范围
     * @param int $appId
     * @param int $env
     * @return array|boolean
     */
    public function getAppLoginServerValidTos($appId, $env = null)
    {
        $appId = (int) $appId;
    	$env = is_null($env) ? $this->_configEnv : (int) $env;
        $sql = "SELECT t.*, t1.area_code, t1.name AS area_name, t2.group_code, t2.name AS group_name, 
        	t3.ip_id AS server_ip_id, t3.ip AS server_ip, t3.alias AS server_alias, 
        	t4.ip_id, t4.ip, t4.alias, t4.environment, t4.idc_type, t4.app_id 
        	FROM app_login_server_valid AS t 
        	LEFT JOIN app_area AS t1 ON t.valid_to_area=t1.id 
        	LEFT JOIN app_group AS t2 ON t.valid_to_group=t2.id 
        	LEFT JOIN app_server AS t3 ON t.valid_to_server=t3.id 
        	LEFT JOIN app_login_server AS t4 ON t.login_server_id=t4.id 
    		WHERE t4.app_id=$appId AND t4.environment=$env 
    		ORDER BY t.id ASC";
        $rows = $this->_oaWebDb->query($sql);
        if ($rows === false) {
        	return false;
        }
        $validTos = array();
        foreach ($rows as $row) {
        	$loginServerId = $row['login_server_id'];
        	if (isset($validTos[$loginServerId])) {
        		$validTos[$loginServerId][] = $row;
        	} else {
        		$validTos[$loginServerId]= array($row);
        	}
        }
        return $validTos;
    }
    
    /**
     * 查询应用登录服务器生效范围数量
     * @param int $appId
     * @param int $env
     * @return array|boolean
     */
    public function getAppLoginServerValidTosCount($appId, $env = null)
    {
        $appId = (int) $appId;
    	$env = is_null($env) ? $this->_configEnv : (int) $env;
        $sql = "SELECT t.login_server_id, COUNT(*) AS cnt 
        	FROM app_login_server_valid AS t 
        	LEFT JOIN app_login_server AS t1 ON t.login_server_id=t1.id 
    		WHERE t1.app_id=$appId AND t1.environment=$env 
        	GROUP BY t.login_server_id";
        $rows = $this->_oaWebDb->query($sql);
        if ($rows === false) {
        	return false;
        }
        $counts = array();
        foreach ($rows as $row) {
        	$counts[$row['login_server_id']]= $row['cnt'];
        }
        return $counts;
    }
    
    /**
     * 修改登录服务器生效范围
     * @param int $id
     * @param array $row
     * @param boolean $sync
     * @return boolean 如果生效范围发生冲突，设置错误号1
     */
    public function modifyLoginServerValidTo($id, $row, $sync = false)
    {
    	$this->_setError();
    	$this->_appLoginServerValidTable->filterFields($row);
        $validRow = $this->getLoginServerValidToById($id);
        if (!is_array($validRow)) {
            $this->_logger->err("valid row not exists: valid_row-$id");
            return false;
        }
        $row = self::filterUnchangedField($row, $validRow);
        if (empty($row)) {
        	return true;
        }
        $oldRow = array();
        foreach ($row as $key => $value) {
        	$oldRow[$key] = $validRow[$key];
        }
        if (isset($row['login_server_id']) || isset($row['valid_to_area']) || 
        	isset($row['valid_to_group']) || isset($row['valid_to_server'])) {
        	$loginServerId = isset($row['login_server_id']) ? $row['login_server_id'] : $validRow['login_server_id'];
        	$validToArea = isset($row['valid_to_area']) ? $row['valid_to_area'] : $validRow['valid_to_area'];
        	$validToGroup = isset($row['valid_to_group']) ? $row['valid_to_group'] : $validRow['valid_to_group'];
        	$validToServer = isset($row['valid_to_server']) ? $row['valid_to_server'] : $validRow['valid_to_server'];
	        if (!$this->checkLoginServerValidTo($loginServerId, $validToArea, 
	        	$validToGroup, $validToServer)) {
	            $this->_setError(1, "already exists");
	            return false;
	        }
        }
        if (!$this->_appLoginServerValidTable->update(array(
            'id' => $id
        ), $row)) {
            $this->_logger->log("modify login server valid row failed");
            return false;
        }
        if ($sync && !OaSyncInfoLogic::syncLoginServerValidToInfo($id, 'update')) {
            $this->_logger->log("sync login server valid row failed, valid_row-$id");
            $this->modifyLoginServerValidTo($id, $oldRow);
            return false;
        }
        $this->_appSvrCfgLogModel->addBackup($validRow['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_UPDATE_LOGIN_SERVER_VALID_TO, 
        	$validRow, $row, $validRow['environment']);
        return true;
    }
    
    /**
     * 设置登录服务器生效范围有效状态
     * @param int $id
     * @param int $status
     * @return boolean
     */
    public function setLoginServerValidToStatus($id, $status)
    {
        return $this->modifyLoginServerValidTo($id, array(
            'status' => $status
        ));
    }
    
    /**
     * 删除登录服务器生效范围
     * @param int $id
     * @param boolean $sync
     * @return boolean
     */
    public function deleteLoginServerValidTo($id, $sync = false)
    {
    	$this->_setError();
        $validRow = $this->getLoginServerValidToById($id);
        if (!is_array($validRow)) {
            $this->_logger->log("login server valid row not exists, valid_row-$id");
            return false;
        }
        if (!$this->_appLoginServerValidTable->delete(array(
            'id' => $id
        ))) {
            $this->_logger->log("delete login server valid row failed");
            return false;
        }
        if ($sync && !OaSyncInfoLogic::syncLoginServerValidToInfo($id, 'delete', $validRow)) {
            $this->_logger->log("sync login server valid row failed, valid_row-$id");
            $this->addLoginServerValidTo($validRow['login_server_id'], $validRow['valid_to_area'], 
            	$validRow['valid_to_group'], $validRow['valid_to_server'], $validRow);
            return false;
        }
        $this->_appSvrCfgLogModel->addBackup($validRow['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_DELETE_LOGIN_SERVER_VALID_TO, 
        	$validRow, array(), $validRow['environment']);
        return true;
    }
    
    /**
     * 删除登录服务器生效范围（批量）
     * @param array $ids
     * @return boolean
     */
    public function deleteLoginServerValidToMulti($ids)
    {
        foreach ($ids as $id) {
            if (!$this->deleteLoginServerValidTo($id)) {
                $this->_logger->log("delete login server valid row failed");
                return false;
            }
        }
        return true;
    }
    
    /**
     * 删除登录服务器生效范围
     * @param int $loginServerId
     * @param boolean $sync
     * @return boolean
     */
    public function deleteLoginServerValidAreaByLoginServerId($loginServerId, $sync = false)
    {
        $validRows = $this->getLoginServerValidTo($loginServerId);
        if ($validRows === false) {
            $this->_logger->log("get login server valid rows of login server failed");
            return false;
        }
        foreach ($validRows as $validRow) {
            if (!$this->deleteLoginServerValidTo($validRow['id'], $sync)) {
                $this->_logger->log("delete login server valid row failed");
                return false;
            }
        }
        return true;
    }
    
    /**
     * 根据生效区ID删除登录服务器生效范围
     * @param int $areaId
     * @param boolean $sync
     * @return boolean
     */
    public function deleteLoginServerValidAreaByValidAreaId($areaId, $sync = false)
    {
        $validRows = $this->_appLoginServerValidTable->get(array(
            'valid_to_area' => $areaId
        ));
        if ($validRows === false) {
            $this->_logger->log("get login server valid rows of area failed");
            return false;
        }
        foreach ($validRows as $validRow) {
            if (!$this->deleteLoginServerValidTo($validRow['id'], $sync)) {
                $this->_logger->log("delete login server valid row failed");
                return false;
            }
        }
        return true;
    }
    
    /**
     * 根据生效组ID删除登录服务器生效范围
     * @param int $groupId
     * @param boolean $sync
     * @return boolean
     */
    public function deleteLoginServerValidAreaByValidGroupId($groupId, $sync = false)
    {
        $validRows = $this->_appLoginServerValidTable->get(array(
            'valid_to_group' => $groupId
        ));
        if ($validRows === false) {
            $this->_logger->log("get login server valid rows of group failed");
            return false;
        }
        foreach ($validRows as $validRow) {
            if (!$this->deleteLoginServerValidTo($validRow['id'], $sync)) {
                $this->_logger->log("delete login server valid row failed");
                return false;
            }
        }
        return true;
    }
    
    /**
     * 根据生效服务器ID删除登录服务器生效范围
     * @param int $serverId
     * @param boolean $sync
     * @return boolean
     */
    public function deleteLoginServerValidAreaByValidServerId($serverId, $sync = false)
    {
        $validRows = $this->_appLoginServerValidTable->get(array(
            'valid_to_server' => $serverId
        ));
        if ($validRows === false) {
            $this->_logger->log("get login server valid rows of server failed");
            return false;
        }
        foreach ($validRows as $validRow) {
            if (!$this->deleteLoginServerValidTo($validRow['id'], $sync)) {
                $this->_logger->log("delete login server valid row failed");
                return false;
            }
        }
        return true;
    }
    
    /**
     * 新建发货服务器
     * @param int $appId
     * @param int $type 接口地址类型
     * @param string $addr 接口地址
     * @param string $ip
     * @param string $alias
     * @param int $idcType
     * @param array $row
     * @param boolean $sync
     * @return int|boolean ip+alias重复时，设置错误号1
     */
    public function addPayServer($appId, $type, $addr, $ip, $alias, $idcType, $row = array(), 
    	$sync = false)
    {
    	$this->_setError();
    	$this->_appPayServerTable->filterFields($row);
        if (!self::checkPayServerAddr($type, $addr)) {
            $this->_logger->err("addr format invalid: type-$type, addr-$addr");
            return false;
        }
        $row = array_merge(array(
            'environment' => $this->_configEnv,
            'app_id' => $appId,
            'type' => $type,
            'addr' => $addr,
            'ip' => $ip,
            'alias' => $alias,
            'idc_type' => $idcType,
            'user_id_type' => self::USER_ID_TYPE_DEFAULT,
            'need_confirm' => self::NEED_CONFIRM,
            'create_time' => date('Y-m-d H:i:s')
        ), $row);
        if (is_array($this->getPayServerByIpAlias($ip, $alias, $row['environment']))) {
            $this->_setError(1, "ip alias duplicated");
            return false;
        }
        $message = '';
        $ipInfo = OASApi::ip($message, array(
        	'clientIp' => $ip, 
        	'alias' => $alias
        ), 'select', $row['environment']);
        if ($ipInfo && $ipInfo['appId'] != $row['app_id']) {
            $this->_setError(1, "ip alias duplicated");
            return false;
        }
        $payServerId = $this->_appPayServerTable->insert($row);
        if ($payServerId === false) {
        	$this->_logger->log("insert failed");
        	return false;
        }
        if ($sync && !OaSyncInfoLogic::syncPayServerInfo($payServerId, 'add')) {
        	$this->_logger->log("sync pay server info failed, pay_server-$payServerId");
        	$this->_appPayServerTable->delete(array(
        	    'id' => $payServerId
        	));
        	return false;
        }
        $this->_appSvrCfgLogModel->addBackup($appId, OaAppServerConfigLogModel::SERVER_CONFIG_OP_ADD_PAY_SERVER, 
        	array(), $row, $row['environment']);
        return $payServerId;
    }
    
    /**
     * 检查发货服务器接口地址
     * @param int $type
     * @param string $addr
     * @return boolean
     */
    public static function checkPayServerAddr($type, $addr)
    {
        if (($type == self::PAY_SERVER_TYPE_URL && preg_match('/^(.+):\/\/([^:\/]+)(:[\d]+)?(\/.+)?/', $addr, $matches)) || 
            ($type == self::PAY_SERVER_TYPE_SOCKET && preg_match('/^([\d.]+):([\d]+)/', $addr, $matches))) {
            return true;
        } else {
            return false;
        }
    }
    
    /**
     * 从发货服务器接口地址解析端口
     * @param int $type
     * @param string $addr
     * @return int
     */
    public static function getPayServerPort($type, $addr)
    {
        $port = -1;
        if ($type == self::PAY_SERVER_TYPE_URL) {
            if (preg_match('/^(.+):\/\/([^:\/]+)(:[\d]+)?(\/.+)?/', $addr, $matches)) {
                if (!empty($matches[3])) {
                    $port = substr($matches[3], 1);
                } else {
                    $port = 80;
                }
            }
        } else if ($type == self::PAY_SERVER_TYPE_SOCKET) {
            if (preg_match('/^([\d.]+):([\d]+)/', $addr, $matches)) {
                $port = $matches[2];
            }
        }
        return $port;
    }
    
    /**
     * 查询发货服务器
     * @param int $serverId
     * @return array|null|boolean
     */
    public function getPayServer($payServerId)
    {
        return $this->_appPayServerTable->getRow(array(
            'id' => $payServerId
        ));
    }
    
    /**
     * 查询发货服务器（批量）
     * @param array $payServerIds
     * @return array|boolean
     */
    public function getPayServerMulti($payServerIds)
    {
        if (empty($payServerIds)) {
            return array();
        }
        foreach ($payServerIds as &$payServerId) {
            $payServerId = (int) $payServerId;
        }
        unset($payServerId);
        $sql = "SELECT * FROM app_pay_server WHERE id IN (" . implode(',', $payServerIds) . ")";
        $rows = $this->_appPayServerTable->query($sql);
        if ($rows === false) {
        	$this->_logger->log("query failed");
            return false;
        }
        $payServers = array();
        foreach ($rows as $row) {
            $payServers[$row['id']] = $row;
        }
        return $payServers;
    }
    
    /**
     * 根据ip和别名查询发货服务器
     * @param string $ip
     * @param string $alias
     * @param string $env
     * @return array|null|boolean 如果没有找到，返回null
     */
    public function getPayServerByIpAlias($ip, $alias, $env = null)
    {
        return $this->_appPayServerTable->getRow(array(
            'environment' => is_null($env) ? $this->_configEnv : $env,
            'ip' => $ip,
            'alias' => $alias
        ));
    }
    
    /**
     * 根据IPID查询发货服务器
     * @param int $ipId
     * @param int $env
     * @return array|null|boolean 如果没有找到，返回null
     */
    public function getPayServerByIpId($ipId, $env = null)
    {
        return $this->_appPayServerTable->getRow(array(
            'environment' => is_null($env) ? $this->_configEnv : $env,
            'ip_id' => $ipId
        ));
    }
    
    /**
     * 查询应用发货服务器列表
     * @param int $appId
     * @param int $env
     * @return array|boolean
     */
    public function getAppPayServers($appId, $env = null)
    {
        return $this->_appPayServerTable->get(array(
            'environment' => is_null($env) ? $this->_configEnv : $env,
            'app_id' => $appId
        ), 0, null, 'id ASC');
    }
    
    /**
     * 搜索发货服务器
     * @param int $appId
     * @param string $ip null表示该参数不起作用 
     * @param string $alias null表示该参数不起作用 
     * @param int $env
     * @return array|boolean
     */
    public function searchPayServers($appId, $ip = null, $alias = null, $env = null)
    {
    	$appId = (int) $appId;
    	if ($ip === '' || $alias === '') {
    		return array();
    	}
    	$env = is_null($env) ? $this->_configEnv : (int) $env;
    	$sql = "SELECT t.* FROM app_pay_server AS t 
    		WHERE app_id=$appId AND environment=$env";
    	if (!is_null($ip)) {
    	    $sql .= " AND t.ip LIKE " . escapeInputValue("%$ip%");
    	}
    	if (!is_null($alias)) {
    	    $sql .= " AND t.alias LIKE " . escapeInputValue("%$alias%");
    	}
    	return $this->_oaWebDb->query($sql);
    }
    
    /**
     * 修改发货服务器
     * @param int $payServerId
     * @param array $row
     * @param boolean $sync
     * @return boolean 如果ip+alias重复，设置错误号1；地址错误，设置错误号2
     */
    public function modifyPayServer($payServerId, $row, $sync = false)
    { 
    	$this->_setError();
    	$this->_appPayServerTable->filterFields($row);
        $payServer = $this->getPayServer($payServerId);
        if (!is_array($payServer)) {
            $this->_logger->log("server not exists");
            return false;
        }
        $row = self::filterUnchangedField($row, $payServer);
        if (empty($row)) {
            return true;
        }
        $oldRow = array();
        foreach ($row as $key => $value) {
        	$oldRow[$key] = $payServer[$key];
        }
        if (isset($row['ip']) || isset($row['alias'])) {
            $ip = isset($row['ip']) ? $row['ip'] : $payServer['ip'];
            $alias = isset($row['alias']) ? $row['alias'] : $payServer['alias'];
            if (is_array($this->getPayServerByIpAlias($ip, $alias, $payServer['environment']))) {
                $this->_setError(1, "ip alias duplicated: ip-$ip, alias-$alias");
                return false;
            }
            $message = '';
            $ipInfo = OASApi::ip($message, array(
            	'clientIp' => $ip, 
            	'alias' => $alias
            ), 'select', $payServer['environment']);
            if ($ipInfo && $ipInfo['appId'] != $payServer['app_id']) {
                $this->_setError(1, "ip alias duplicated");
                return false;
            }
        }
        $type = isset($row['type']) ? $row['type'] : $payServer['type'];
        if (isset($row['addr']) && !self::checkPayServerAddr($type, $row['addr'])) {
            $this->_setError(2, "pay server addr invalid: addr-{$row['addr']}");
            return false;
        }
        if (!$this->_appPayServerTable->update(array(
            'id' => $payServerId
        ), $row)) {
        	$this->_logger->log("update failed");
        	return false;
        }
        if ($sync == true) {
            $newPayServer = array_merge($payServer, $row);
            $newPayServer['old_ip'] = $payServer['ip'];
            $newPayServer['old_alias'] = $payServer['alias'];
            if (!OaSyncInfoLogic::syncPayServerInfo($payServerId, 'update', $newPayServer)) {
                $this->_logger->log("sync pay server info failed, op-update, pay_server-$payServerId");
                $this->modifyPayServer($payServerId, $oldRow);
                return false;
            }
	        $payServerValidTos = $this->getPayServerValidTo($payServerId);
	        foreach ($payServerValidTos as $validTo) {
		        if (!OaSyncInfoLogic::syncPayServerValidToInfo($validTo['id'], 'update', $validTo)) {
		            $this->_logger->log("sync pay server valid info failed, op-update, " . 
		            	"valid_row-{$validTo['id']}");
		        }
	        }
        }
        $this->_appSvrCfgLogModel->addBackup($payServer['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_UPDATE_PAY_SERVER, 
        	$payServer, $row, $payServer['environment']);
        return true;
    }
    
    /**
     * 删除发货服务器
     * @param int $payServerId
     * @param boolean $sync
     * @return boolean
     */
    public function deletePayServer($payServerId, $sync = false)
    {
    	$this->_setError();
        $payServer = $this->getPayServer($payServerId);
        if (!is_array($payServer)) {
        	$this->_logger->log("pay server not exists, pay_server-$payServerId");
        	return false;
        }
        if ($this->deletePayServerValidAreaByPayServerId($payServerId, $sync) === false) {
            $this->_logger->log("delete valid area of pay server failed");
            return false;
        }
        if (!$this->_appPayServerTable->delete(array(
            'id' => $payServerId
        ))) {
        	$this->_logger->log("delete failed");
        	return false;
        }
        if ($sync && !OaSyncInfoLogic::syncPayServerInfo($payServerId, 'delete', $payServer)) {
        	$this->_logger->log("sync pay server info failed, op-delete, pay_server-$payServerId");
        	$this->addPayServer($payServer['app_id'], $payServer['type'], $payServer['addr'], 
        		$payServer['ip'], $payServer['alias'], $payServer['idc_type'], $payServer);
        	return false;
        }
        $this->_appSvrCfgLogModel->addBackup($payServer['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_DELETE_PAY_SERVER, 
        	$payServer, array(), $payServer['environment']);
        return true;
    }
    
    /**
     * 删除应用发货服务器
     * @param int $appId
     * @param int $env
     * @return boolean
     */
    public function deleteAppPayServers($appId, $env = null)
    {
    	$payServers = $this->_appPayServerTable->get(array(
        	'environment' => is_null($env) ? $this->_configEnv : $env,
            'app_id' => $appId   		
    	));
		foreach($payServers as $payServer){
			$this->deletePayServer($payServer['id']);
		}
    }
    
    /**
     * 增加发货服务器生效范围
     * @param int $payServerId
     * @param int $validToArea
     * @param int $validToGroup
     * @param int $validToServer
     * @param array $row
     * @param boolean $sync
     * @return int|boolean 如果该生效范围已经配置过，设置错误号1
     */
    public function addPayServerValidTo($payServerId, $validToArea = -1, $validToGroup = -1, 
        $validToServer = -1, $row = array(), $sync = false)
    {
    	$this->_setError();
    	$this->_appPayServerValidTable->filterFields($row);
        $payServer = $this->getPayServer($payServerId);
        if (!is_array($payServer)) {
            $this->_logger->log("pay server not exists");
            return false;
        }
        $appId = $payServer['app_id'];
        $env = $payServer['environment'];
        $rows = $this->getPayServerValidToByAGS($validToArea, $validToGroup, $validToServer, 
            $appId, $env);
        if (!empty($rows)) {
            $this->_setError(1, "valid area already have a pay server");
            return false;
        }
        $row = array_merge(array(
            'valid_to_area' => $validToArea,
            'valid_to_group' => $validToGroup,
            'valid_to_server' => $validToServer,
            'pay_server_id' => $payServerId,
            'status' => self::PAY_SERVER_STATUS_VALID
        ), $row);
        $id = $this->_appPayServerValidTable->insert($row);
        if ($id === false) {
        	$this->_logger->log("insert failed");
        	return false;
        }
        if ($sync && !OaSyncInfoLogic::syncPayServerValidToInfo($id, 'add')) {
            $this->_logger->log("sync pay server valid row failed, vali_row-$id");
            $this->_appPayServerValidTable->delete(array(
                'id' => $id
            ));
            return false;
        }
        $this->_appSvrCfgLogModel->addBackup($payServer['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_ADD_PAY_SERVER_VALID_TO, 
        	array(), $row, $payServer['environment']);        
        return $id;
    }
    
    /**
     * 查询发货服务器生效范围（根据自增长ID）
     * @param int $id
     * @return array|null|boolean
     */
    public function getPayServerValidToById($id)
    {
        $id = (int) $id;
        $sql = "SELECT t.*, t1.area_code, t1.name AS area_name, t2.group_code, t2.name AS group_name, 
        	t3.ip_id AS server_ip_id, t3.ip AS server_ip, t3.alias AS server_alias, 
        	t4.ip_id, t4.ip, t4.alias, t4.environment, t4.type, t4.addr, t4.idc_type, 
        	t4.need_confirm, t4.user_id_type, t4.app_id 
        	FROM app_pay_server_valid AS t 
    		LEFT JOIN app_area AS t1 ON t.valid_to_area=t1.id 
    		LEFT JOIN app_group AS t2 ON t.valid_to_group=t2.id 
    		LEFT JOIN app_server AS t3 ON t.valid_to_server=t3.id 
    		LEFT JOIN app_pay_server AS t4 ON t.pay_server_id=t4.id 
    		WHERE t.id=$id";
        return $this->_oaWebDb->queryRow($sql);
    }
    
    /**
     * 查询发货服务器生效范围（根据区、组、服务器）
     * @param int $validToArea
     * @param int $validToGroup
     * @param int $validToServer
     * @param int $appId
     * @param int $env
     * @return array|boolean
     */
    public function getPayServerValidToByAGS($validToArea, $validToGroup = null, 
    	$validToServer = null, $appId = null, $env = null)
    {
        $validToArea = (int) $validToArea;
        $sql = "SELECT t.*, t1.area_code, t1.name AS area_name, t2.group_code, t2.name AS group_name, 
        	t3.ip_id AS server_ip_id, t3.ip AS server_ip, t3.alias AS server_alias, 
        	t4.ip_id, t4.ip, t4.alias, t4.environment, t4.type, t4.addr, t4.idc_type, 
        	t4.need_confirm, t4.user_id_type, t4.app_id 
        	FROM app_pay_server_valid AS t 
    		LEFT JOIN app_area AS t1 ON t.valid_to_area=t1.id 
    		LEFT JOIN app_group AS t2 ON t.valid_to_group=t2.id 
    		LEFT JOIN app_server AS t3 ON t.valid_to_server=t3.id 
    		LEFT JOIN app_pay_server AS t4 ON t.pay_server_id=t4.id 
    		WHERE t.valid_to_area=$validToArea"; 
    	if (!is_null($validToGroup)) {
        	$validToGroup = (int) $validToGroup;
            $sql .= " AND t.valid_to_group=$validToGroup";
        }
    	if (!is_null($validToServer)) {
        	$validToServer = (int) $validToServer;
            $sql .= " AND t.valid_to_server=$validToServer";
        }
        if (!is_null($appId)) {
            $appId = (int) $appId;
            $sql .= " AND t4.app_id=$appId";
        }
        if (!is_null($env)) {
            $env = (int) $env;
            $sql .= " AND t4.environment=$env";
        }
        $sql .= " ORDER BY t.id ASC";
        return $this->_oaWebDb->query($sql);
    }
    
    /**
     * 查询发货服务器生效范围（根据发货服务器）
     * @param int $payServerId
     * @return array|boolean
     */
    public function getPayServerValidTo($payServerId)
    {
        $payServerId = (int) $payServerId;
        $sql = "SELECT t.*, t1.area_code, t1.name AS area_name, t2.group_code, t2.name AS group_name, 
        	t3.ip_id AS server_ip_id, t3.ip AS server_ip, t3.alias AS server_alias, 
        	t4.ip_id, t4.ip, t4.alias, t4.environment, t4.type, t4.addr, t4.idc_type, 
        	t4.need_confirm, t4.user_id_type, t4.app_id 
        	FROM app_pay_server_valid AS t 
    		LEFT JOIN app_area AS t1 ON t.valid_to_area=t1.id 
    		LEFT JOIN app_group AS t2 ON t.valid_to_group=t2.id 
    		LEFT JOIN app_server AS t3 ON t.valid_to_server=t3.id 
    		LEFT JOIN app_pay_server AS t4 ON t.pay_server_id=t4.id 
    		WHERE t.pay_server_id=$payServerId 
    		ORDER BY t.id ASC";
        return $this->_oaWebDb->query($sql);
    }
    
    /**
     * 查询应用发货服务器生效范围
     * @param int $appId
     * @param int $env
     * @return array|boolean
     */
    public function getAppPayServerValidTos($appId, $env = null)
    {
    	if (is_null($env)) {
        	$env = $this->_configEnv;
    	}
        $appId = (int) $appId;
        $env = (int) $env;
        $sql = "SELECT t.*, t1.area_code, t1.name AS area_name, t2.group_code, t2.name AS group_name, 
        	t3.ip_id AS server_ip_id, t3.ip AS server_ip, t3.alias AS server_alias, 
        	t4.ip_id, t4.ip, t4.alias, t4.environment, t4.type, t4.addr, t4.idc_type, 
        	t4.need_confirm, t4.user_id_type, t4.app_id 
        	FROM app_pay_server_valid AS t 
    		LEFT JOIN app_area AS t1 ON t.valid_to_area=t1.id 
    		LEFT JOIN app_group AS t2 ON t.valid_to_group=t2.id 
    		LEFT JOIN app_server AS t3 ON t.valid_to_server=t3.id 
    		LEFT JOIN app_pay_server AS t4 ON t.pay_server_id=t4.id 
    		WHERE t4.app_id=$appId AND t4.environment=$env 
    		ORDER BY t.id ASC";
        $rows = $this->_oaWebDb->query($sql);
        if ($rows === false) {
        	return false;
        }
        $validTos = array();
        foreach ($rows as $row) {
        	$payServerId = $row['pay_server_id'];
        	if (isset($validTos[$payServerId])) {
        		$validTos[$payServerId][] = $row;
        	} else {
        		$validTos[$payServerId]= array($row);
        	}
        }
        return $validTos;
    }
    
    /**
     * 查询应用发货服务器生效范围数量
     * @param int $appId
     * @param int $env
     * @return array|boolean
     */
    public function getAppPayServerValidTosCount($appId, $env = null)
    {
        $appId = (int) $appId;
    	$env = is_null($env) ? $this->_configEnv : (int) $env;
        $sql = "SELECT t.pay_server_id, COUNT(*) AS cnt 
        	FROM app_pay_server_valid AS t 
        	LEFT JOIN app_pay_server AS t1 ON t.pay_server_id=t1.id 
    		WHERE t1.app_id=$appId AND t1.environment=$env 
        	GROUP BY t.pay_server_id";
        $rows = $this->_oaWebDb->query($sql);
        if ($rows === false) {
        	return false;
        }
        $counts = array();
        foreach ($rows as $row) {
        	$counts[$row['pay_server_id']]= $row['cnt'];
        }
        return $counts;
    }
    
    /**
     * 修改发货服务器生效范围
     * @param int $id
     * @param array $row
     * @param boolean $sync
     * @return boolean 如果生效范围发生冲突，设置错误号1
     */
    public function modifyPayServerValidTo($id, $row, $sync = false)
    {
    	$this->_setError();
    	$this->_appPayServerValidTable->filterFields($row);
        $validRow = $this->getPayServerValidToById($id);
        if (!is_array($validRow)) {
            $this->_logger->err("valid row not exists: valid_row-$id");
            return false;
        }
        $row = self::filterUnchangedField($row, $validRow);
        if (empty($row)) {
        	return true;
        }
        $oldRow = array();
        foreach ($row as $key => $value) {
        	$oldRow[$key] = $validRow[$key];
        }
        if (isset($row['valid_to_area']) || isset($row['valid_to_group']) || 
        	isset($row['valid_to_server'])) {
        	$validToArea = isset($row['valid_to_area']) ? $row['valid_to_area'] : $validRow['valid_to_area'];
        	$validToGroup = isset($row['valid_to_group']) ? $row['valid_to_group'] : $validRow['valid_to_group'];
        	$validToServer = isset($row['valid_to_server']) ? $row['valid_to_server'] : $validRow['valid_to_server'];
        	$validRows = $this->getPayServerValidToByAGS($validToArea, $validToGroup, $validToServer, 
            	$validRow['app_id'], $validRow['environment']);
	        if (!empty($validRows)) {
	            $this->_setError(1, "valid area already have a pay server");
	            return false;
	        }
        }
        if (!$this->_appPayServerValidTable->update(array(
            'id' => $id
        ), $row)) {
        	$this->_logger->log("update failed");
        	return false;
        }
        if ($sync && !OaSyncInfoLogic::syncPayServerValidToInfo($id, 'update')) {
            $this->_logger->log("sync pay server valid info failed, valid_row-$id");
            $this->modifyPayServerValidTo($id, $oldRow);
            return false;
        }
        $this->_appSvrCfgLogModel->addBackup($validRow['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_UPDATE_PAY_SERVER_VALID_TO, 
        	$validRow, $row, $validRow['environment']);
        return true;
    }
    
    /**
     * 设置发货服务器生效范围有效状态
     * @param int $id
     * @param int $status
     * @return boolean
     */
    public function setPayServerValidToStatus($id, $status)
    {
        return $this->modifyPayServerValidTo($id, array(
            'status' => $status
        ));
    }
    
    /**
     * 删除发货服务器生效范围
     * @param int $id
     * @param boolean $sync
     * @return boolean
     */
    public function deletePayServerValidTo($id, $sync = false)
    {
    	$this->_setError();
        $validRow = $this->getPayServerValidToById($id);
        if (!is_array($validRow)) {
        	$this->_logger->log("pay server valid row not exists, valid_row-$id");
        	return false;
        }
        if (!$this->_appPayServerValidTable->delete(array(
            'id' => $id
        ))) {
        	$this->_logger->log("delete failed");
        	return false;
        }
        if ($sync && !OaSyncInfoLogic::syncPayServerValidToInfo($id, 'delete', $validRow)) {
        	$this->_logger->log("sync pay server valid row failed, valid_row-$id");
        	$this->addPayServerValidTo($validRow['pay_server_id'], $validRow['valid_to_area'], 
            	$validRow['valid_to_group'], $validRow['valid_to_server'], $validRow);
        	return false;
        }
        $this->_appSvrCfgLogModel->addBackup($validRow['app_id'], OaAppServerConfigLogModel::SERVER_CONFIG_OP_DELETE_PAY_SERVER_VALID_TO, 
        	$validRow, array(), $validRow['environment']);
        return true;
    }
    
    /**
     * 删除发货服务器生效范围（批量）
     * @param array $ids
     * @return boolean
     */
    public function deletePayServerValidToMulti($ids)
    {
        foreach ($ids as $id) {
            if (!$this->deletePayServerValidTo($id)) {
                $this->_logger->log("delete pay server valid row failed");
                return false;
            }
        }
        return true;
    }
    
    /**
     * 根据发货服务器ID删除发货服务器生效范围
     * @param int $payServerId
     * @param boolean $sync
     * @return boolean
     */
    public function deletePayServerValidAreaByPayServerId($payServerId, $sync = false)
    {
        $validRows = $this->getPayServerValidTo($payServerId);
        if ($validRows === false) {
            $this->_logger->log("get pay server valid rows of pay server failed");
            return false;
        }
        foreach ($validRows as $validRow) {
            if (!$this->deletePayServerValidTo($validRow['id'], $sync)) {
                $this->_logger->log("delete login server valid row failed");
                return false;
            }
        }
    }
    
    /**
     * 根据生效区ID删除发货服务器生效范围
     * @param int $areaId
     * @param boolean $sync
     * @return boolean
     */
    public function deletePayServerValidAreaByValidAreaId($areaId, $sync = false)
    {
        $validRows = $this->_appPayServerValidTable->get(array(
            'valid_to_area' => $areaId
        ));
        if ($validRows === false) {
            $this->_logger->log("get pay server valid rows of area failed");
            return false;
        }
        foreach ($validRows as $validRow) {
            if (!$this->deletePayServerValidTo($validRow['id'], $sync)) {
                $this->_logger->log("delete pay server valid row failed");
                return false;
            }
        }
        return true;
    }
    
    /**
     * 根据生效组ID删除发货服务器生效范围
     * @param int $groupId
     * @param boolean $sync
     * @return boolean
     */
    public function deletePayServerValidAreaByValidGroupId($groupId, $sync = false)
    {
        $validRows = $this->_appPayServerValidTable->get(array(
            'valid_to_group' => $groupId
        ));
        if ($validRows === false) {
            $this->_logger->log("get pay server valid rows of group failed");
            return false;
        }
        foreach ($validRows as $validRow) {
            if (!$this->deletePayServerValidTo($validRow['id'], $sync)) {
                $this->_logger->log("delete pay server valid row failed");
                return false;
            }
        }
        return true;
    }
    
    /**
     * 根据生效服务器ID删除发货服务器生效范围
     * @param int $serverId
     * @param boolean $sync
     * @return boolean
     */
    public function deletePayServerValidAreaByValidServerId($serverId, $sync = false)
    {
        $validRows = $this->_appPayServerValidTable->get(array(
            'valid_to_server' => $serverId
        ));
        if ($validRows === false) {
            $this->_logger->log("get pay server valid rows of server failed");
            return false;
        }
        foreach ($validRows as $validRow) {
            if (!$this->deletePayServerValidTo($validRow['id'], $sync)) {
                $this->_logger->log("delete pay server valid row failed");
                return false;
            }
        }
        return true;
    }
    
    /**
     * 获取连调或正式环境对应区ID
     * @param int $areaId
     * @return int 如果指定区不存在，返回-1
     */
    public function getAreaMapId($areaId)
    {
        $area = $this->getArea($areaId);
        if (is_array($area)) {
            return $area['map_id'];
        } else {
            return -1;
        }
    }
    
    /**
     * 获取连调或正式环境对应组ID
     * @param int $groupId
     * @return int 如果指定组不存在，返回-1
     */
    public function getGroupMapId($groupId)
    {
        $group = $this->getGroup($groupId);
        if (is_array($group)) {
            return $group['map_id'];
        } else {
            return -1;
        }
    }
    
    /**
     * 获取连调或正式环境对应服务器ID
     * @param int $serverId
     * @return int 如果指定服务器不存在，返回-1
     */
    public function getServerMapId($serverId)
    {
        $server = $this->getServer($serverId);
        if (is_array($server)) {
            return $server['map_id'];
        } else {
            return -1;
        }
    }
    
    /**
     * 获取连调或正式环境对应登录服务器ID
     * @param int $loginServerId
     * @return int 如果指定登录服务器不存在，返回-1
     */
    public function getLoginServerMapId($loginServerId)
    {
        $loginServer = $this->getLoginServer($loginServerId);
        if (is_array($loginServer)) {
            return $loginServer['map_id'];
        } else {
            return -1;
        }
    }
    
    /**
     * 获取连调或正式环境对应登录服务器生效范围ID
     * @param int $validId
     * @return int 如果指定生效范围不存在，返回-1
     */
    public function getLoginServerValidMapId($validId)
    {
        $validRow = $this->getLoginServerValidToById($validId);
        if (is_array($validRow)) {
            return $validRow['map_id'];
        } else {
            return -1;
        }
    }
    
    /**
     * 获取连调或正式环境对应发货服务器ID
     * @param int $payServerId
     * @return int 如果指定发货服务器不存在，返回-1
     */
    public function getPayServerMapId($payServerId)
    {
        $payServer = $this->getPayServer($payServerId);
        if (is_array($payServer)) {
            return $payServer['map_id'];
        } else {
            return -1;
        }
    }
    
    /**
     * 获取连调或正式环境对应发货服务器生效范围ID
     * @param int $validId
     * @return int 如果指定生效范围不存在，返回-1
     */
    public function getPayServerValidMapId($validId)
    {
        $validRow = $this->getPayServerValidToById($validId);
        if (is_array($validRow)) {
            return $validRow['map_id'];
        } else {
            return -1;
        }
    }
    
    /**
     * 过滤掉没有改变的字段
     * @param array $row
     * @param array $oldRow
     * @return array
     */
    public static function filterUnchangedField($row, $oldRow)
    {
    	foreach ($row as $key => $value) {
    		if (isset($oldRow[$key]) && $row[$key] == $oldRow[$key]) {
    			unset($row[$key]);
    		}
    	}
    	return $row;
    }
}